<?php

/***
 * Class CW_DateAndTimeClass provides a set of methods for timestamp comparisons
 * and modifications.
 ***/
class CW_DateAndTimeClass {


   /**
	* Optionally passed timestamp
	* @access Private
	* @var Integer
	*/
	private $timestamp;


   /**
	* Current timestamp
	* @access Private
	* @var Integer
	*/
	private $time_current;


   /**
	* Difference between current time and passed time
	* @access Private
	* @var Integer
	*/
	private $time_difference;


   /**
	* Used to determine whether the passed through timestamp
	* takes place in the future
	* @access Private
	* @var Boolean
	*/
	private $time_in_future;


   /**
	* Elapsed seconds
	* @access Private
	* @var Integer
	*/
	private $seconds;


   /**
	* Elapsed minutes
	* @access Private
	* @var Integer
	*/
	private $minutes;


   /**
	* Elapsed hours
	* @access Private
	* @var Integer
	*/
	private $hours;


   /**
	* Elapsed days
	* @access Private
	* @var Integer
	*/
	private $days;


   /**
	* Elapsed weeks
	* @access Private
	* @var Integer
	*/
	private $weeks;


   /**
	* Elapsed months
	* @access Private
	* @var Integer
	*/
	private $months;


   /**
	* Elapsed years
	* @access Private
	* @var Integer
	*/
	private $years;


   // ! Constructor Method

   /**
	* Instantiates class and defines instance variables.
	*
	* @param Integer $timestamp Optional timestamp
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access public
	* @return Void
	*/
	public function __construct($timestamp = null)
	{
		$this->timestamp = $timestamp;
		$this->time_current = time();

		if(($this->time_difference = $this->time_current - $this->timestamp) < 0)
		{
			$this->time_difference = abs($this->time_difference);
			$this->time_in_future = true;
		}
		else
		{
			$this->time_in_future = false;
		}

		$this->years = floor($this->time_difference / 31536000);
		$this->time_difference -= $this->years * 31536000;

		$this->months = floor($this->time_difference / 2592000);
		$this->time_difference -= $this->months * 2592000;

		$this->weeks = floor($this->time_difference / 604800);
		$this->time_difference -= $this->weeks * 604800;

		$this->days = floor($this->time_difference / 86400);
		$this->time_difference -= $this->days * 86400;

		$this->hours = floor($this->time_difference / 3600);
		$this->time_difference -= $this->hours * 3600;

		$this->minutes = floor($this->time_difference / 60);
		$this->time_difference -= $this->minutes * 60;

		$this->seconds = $this->time_difference;
	}


   // ! Executor Method

   /**
	* Is the passed through timestamp from last year?
	*
	* @param None
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Boolean
	*/
	public function isLastYear()
	{
		if(date('Y', $this->timestamp) == date('Y', $this->time_current) - 1)
		{
			return true;
		}

		return false;
	}


   // ! Executor Method

   /**
	* Is the passed through timestamp from last month?
	*
	* @param None
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Boolean
	*/
	public function isLastMonth()
	{
		if(date('Ym', $this->timestamp) == date('Ym', $this->time_current) - 1)
		{
			return true;
		}

		return false;
	}


   // ! Executor Method

   /**
	* Is the passed through timestamp from last week?
	*
	* @param None
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Boolean
	*/
	public function isLastWeek()
	{
		if(date('YW', $this->timestamp) == date('YW', $this->time_current) - 1)
		{
			return true;
		}

		return false;
	}


   // ! Executor Method

   /**
	* Is the passed through timestamp from yesterday?
	*
	* @param None
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Boolean
	*/
	public function isYesterday()
	{
		if(date('Ymd', $this->timestamp) == date('Ymd', $this->time_current) - 1)
		{
			return true;
		}

		return false;
	}


   // ! Executor Method

   /**
	* Is the passed through timestamp from today?
	*
	* @param None
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Boolean
	*/
	public function isToday()
	{
		if(date('Ymd', $this->timestamp) == date('Ymd', $this->time_current) )
		{
			return true;
		}

		return false;
	}


   // ! Executor Method

   /**
	* Is the passed through timestamp from tomorrow?
	*
	* @param None
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Boolean
	*/
	public function isTomorrow()
	{
		if(date('Ymd', $this->timestamp) == date('Ymd', $this->time_current) + 1)
		{
			return true;
		}

		return false;
	}


   // ! Executor Method

   /**
	* Is the passed through timestamp from next week?
	*
	* @param None
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Boolean
	*/
	public function isNextWeek()
	{
		if(date('YW', $this->timestamp) == date('YW', $this->time_current) + 1)
		{
			return true;
		}

		return false;
	}


   // ! Executor Method

   /**
	* Is the passed through timestamp from next month?
	*
	* @param None
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Boolean
	*/
	public function isNextMonth()
	{
		if(date('Ym', $this->timestamp) == date('Ym', $this->time_current) + 1)
		{
			return true;
		}

		return false;
	}


   // ! Executor Method

   /**
	* Is the passed through timestamp from next year?
	*
	* @param None
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Boolean
	*/
	public function isNextYear()
	{
		if(date('Y', $this->timestamp) == date('Y', $this->time_current) + 1)
		{
			return true;
		}

		return false;
	}


   // ! Accessor Method

   /**
	* Is the passed through timestamp from the future?
	*
	* @param None
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Boolean
	*/
	public function isFutureDate()
	{
		return $this->time_in_future;
	}


   // ! Accessor Method

   /**
	* Returns years elapsed
	*
	* @param None
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Integer
	*/
	public function returnYears()
	{
		return $this->years;
	}


   // ! Accessor Method

   /**
	* Returns months elapsed
	*
	* @param None
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Integer
	*/
	public function returnMonths()
	{
		return $this->months;
	}


   // ! Accessor Method

   /**
	* Returns weeks elapsed
	*
	* @param None
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Integer
	*/
	public function returnWeeks()
	{
		return $this->weeks;
	}


   // ! Accessor Method

   /**
	* Returns days elapsed
	*
	* @param None
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Integer
	*/
	public function returnDays()
	{
		return $this->days;
	}


   // ! Accessor Method

   /**
	* Returns hours elapsed
	*
	* @param None
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Integer
	*/
	public function returnHours()
	{
		return $this->hours;
	}


   // ! Accessor Method

   /**
	* Returns minutes elapsed
	*
	* @param None
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Integer
	*/
	public function returnMinutes()
	{
		return $this->minutes;
	}


   // ! Accessor Method

   /**
	* Returns seconds elapsed
	*
	* @param None
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Integer
	*/
	public function returnSeconds()
	{
		return $this->seconds;
	}


   // ! Executor Method

   /**
	* Takes a timestamp and a specified date representation
	* and returns a standards compliant date.
	*
	* Note: To get the timestamp back, use strtotime();
	*
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Mixed
	*/
	public function getCompliantDate($standard = null, $timestamp = false)
	{
		if(false == $timestamp)
		{
			$timestamp = $this->time_current;
		}

		switch($standard)
		{
			default:
			case DATE_ATOM: return date(DATE_ATOM, $timestamp);
			case DATE_COOKIE: return date(DATE_COOKIE, $timestamp);
			case DATE_ISO8601: return date(DATE_ISO8601, $timestamp);
			case DATE_RFC822: return date(DATE_RFC822,  $timestamp);
			case DATE_RFC850: return date(DATE_RFC850, $timestamp);
			case DATE_RFC1036: return date(DATE_RFC1036, $timestamp);
			case DATE_RFC1123: return date(DATE_RFC1123, $timestamp);
			case DATE_RFC2822: return date(DATE_RFC2822, $timestamp);
			case DATE_RSS: return date(DATE_RSS, $timestamp);
			case DATE_W3C: return date(DATE_W3C, $timestamp);
		}

		return false;
	}


   // ! Executor Method

   /**
	* Adds a unit of time to a given timestamp.
	*
	* @param $time Timestamp to add time to
	* @param $count Number of units to add
	* @param $unit Type of time to add
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Integer
	*/
	public function addToTime($count, $unit = 'hours', $timestamp = null)
	{
		if(false == $timestamp)
		{
			$timestamp = $this->time_current;
		}

		$product = 0;

		switch($unit)
		{
			case 'hours': $product = 60 * 60; break;
			case 'days':  $product = (60 * 60) * 24; break;
			case 'weeks': $product = ((60 * 60) * 24) * 7; break;
			case 'years': $product = ((60 * 60) * 24) * 365; break;
		}

		return $timestamp + ($count * $product);
	}


   // ! Executor Method

   /**
	* Takes a timestamp and accurately modifies it according to
	* several environmental variables including server timezone,
	* daylight savings and more.
	*
	* @param $format How to format the resulting timestamp
	* @param $server_timezone The timezone of the server
	* @param $timestamp The timestamp to modify
	* @param $user_timezone The timezone of a current user, if any
	* @param $dst Determines whether to take daylight savings into consideration
	* @param $return_timestamp Returns a timestamp rather than a formatted date
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Integer
	*/
	public function formatDate($format, $server_timezone, $timestamp = false, $user_timezone = false, $dst = false, $return_timestamp = false)
	{
		if(false == $timestamp)
		{
			$timestamp = $this->time_current;
		}

		$timestamp += $user_timezone ? $user_timezone : $server_timezone * 3600;

		if($dst)
		{
			$timestamp += 3600;
		}

		return $return_timestamp ? $timestamp : gmdate($format, $timestamp);
	}
}

?>